package com.carassistant.beta.common;
 
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.ReferenceQueue;
import java.util.Hashtable;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.util.TypedValue;
/**
 * 防止溢出
 *
 */
public class BitmapCache {
	private static BitmapCache cache;
	/** 用于Chche内容的存储 */
	private Hashtable<String, BitmapRef> bitmapRefs;
	/** 垃圾Reference的队列（所引用的对象已经被回收，则将该引用存入队列中） */
	private ReferenceQueue<Bitmap> queue;
 
	private BitmapCache() {
		bitmapRefs = new Hashtable<String, BitmapRef>();
		queue = new ReferenceQueue<Bitmap>(); 
	}

	/**
	 * 取得缓存器实例
	 */
	public static BitmapCache getInstance() {
		if (cache == null) {
			cache = new BitmapCache();
		}
		return cache; 
	}

	/**
	 * 以软引用的方式对一个Bitmap对象的实例进行引用并保存该引用
	 * @param bmp
	 * @param key
	 */
	private void addCacheBitmap(String key, Bitmap bmp) {
		cleanCache();// 清除垃圾引用
		BitmapRef ref = new BitmapRef(bmp, queue, key);
		bitmapRefs.put(key, ref);
	}

	/**
	 * 依据所指定的文件名获取图片
	 */
	public Bitmap getBitmap(String imagePath) {

		Bitmap bitmapImage = null;
		// 缓存中是否有该Bitmap实例的软引用，如果有，从软引用中取得。
		if (bitmapRefs.containsKey(imagePath)) {
			BitmapRef ref = (BitmapRef) bitmapRefs.get(imagePath);
			bitmapImage = (Bitmap) ref.get();
		}
		// 如果没有软引用，或者从软引用中得到的实例是null，重新构建一个实例，
		// 并保存对这个新建实例的软引用
		if (bitmapImage == null) { 
			bitmapImage = BitmapFactory.decodeFile(imagePath); 
			this.addCacheBitmap(imagePath, bitmapImage); 
		} 
		return bitmapImage;
	}

	/**
	 * 依据所指定的文件名获取图片
	 * BitmapFactory.decodeStream
	 */
	public Bitmap getBitmap(Resources res, int bit) {
		Bitmap bitmapImage = null;
		// 缓存中是否有该Bitmap实例的软引用，如果有，从软引用中取得。
		if (bitmapRefs.containsKey(String.valueOf(bit))) {
			BitmapRef ref = (BitmapRef) bitmapRefs.get(String.valueOf(bit));
			bitmapImage = (Bitmap) ref.get();
		}
		// 如果没有软引用，或者从软引用中得到的实例是null，重新构建一个实例，
		// 并保存对这个新建实例的软引用
		if (bitmapImage == null) { 
			BitmapFactory.Options opt = new BitmapFactory.Options();  
		    opt.inPreferredConfig = Bitmap.Config.RGB_565;   
		    opt.inPurgeable = true;  
		    opt.inInputShareable = true;  
		    opt.inSampleSize = 2;
		       //获取资源图片  
		    InputStream is = res.openRawResource(bit); 
		    bitmapImage = BitmapFactory.decodeStream(is,null,opt);
		    this.addCacheBitmap(String.valueOf(bit), bitmapImage); 
		    try {
		    	if(is!=null){
		    		is.close();
		    	}		
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	    return  bitmapImage;
	}
	
	/**
	 * 依据所指定的文件名获取图片 原图
	 * BitmapFactory.decodeStream
	 */
	public Bitmap getBitmap2(Resources res, int bit) {
		Bitmap bitmapImage = null;
		// 缓存中是否有该Bitmap实例的软引用，如果有，从软引用中取得。
		if (bitmapRefs.containsKey(String.valueOf(bit))) {
			BitmapRef ref = (BitmapRef) bitmapRefs.get(String.valueOf(bit));
			bitmapImage = (Bitmap) ref.get();
		}
		// 如果没有软引用，或者从软引用中得到的实例是null，重新构建一个实例，
		// 并保存对这个新建实例的软引用
		if (bitmapImage == null) { 
			TypedValue value = new TypedValue();
			res.openRawResource(bit,value);
			
			BitmapFactory.Options opt = new BitmapFactory.Options();  
		    opt.inPreferredConfig = Bitmap.Config.RGB_565;   
		    opt.inPurgeable = true;  
		    opt.inInputShareable = true;  
		    opt.inTargetDensity = value.density;
		       //获取资源图片  
		    InputStream is = res.openRawResource(bit); 
		    bitmapImage = BitmapFactory.decodeStream(is,null,opt);
		    this.addCacheBitmap(String.valueOf(bit), bitmapImage); 
		    try {
		    	if(is!=null){
		    		is.close();
		    	}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		 
	    return  bitmapImage;
	}
	
	/**
	 * 依据所指定的文件名获取图片
	 * BitmapFactory.decodeResource
	 */
	public Bitmap getBitmap3(Resources res, int bit) {
		Bitmap bitmapImage = null;
		// 缓存中是否有该Bitmap实例的软引用，如果有，从软引用中取得。
		if (bitmapRefs.containsKey(String.valueOf(bit))) {
			BitmapRef ref = (BitmapRef) bitmapRefs.get(String.valueOf(bit));
			bitmapImage = (Bitmap) ref.get();
		}
		// 如果没有软引用，或者从软引用中得到的实例是null，重新构建一个实例，
		// 并保存对这个新建实例的软引用
		if (bitmapImage == null) { 
			TypedValue value = new TypedValue();
			res.openRawResource(bit,value);
			BitmapFactory.Options opt = new BitmapFactory.Options();
			opt.inTargetDensity = value.density;
			opt.inPurgeable = true;  
		    opt.inInputShareable = true;  
			bitmapImage = BitmapFactory.decodeResource(res, bit, opt);
			this.addCacheBitmap(String.valueOf(bit), bitmapImage); 
		} 
		
		return bitmapImage;
	}
	
	private void cleanCache() {
		BitmapRef ref = null;
		while ((ref = (BitmapRef) queue.poll()) != null) {
			System.out.println("romove key=" + ref.key);
			bitmapRefs.remove(ref.key);
			ref.clear();
		}
	}

	// 清除Cache内的全部内容
	public void clearCache() {
		cleanCache();
		bitmapRefs.clear();
		System.gc();
		System.runFinalization();
	} 
	
	public static byte[] bitmap2bytes(Bitmap bitmap) { 
        int size = bitmap.getWidth() * bitmap.getHeight() * 4;
        ByteArrayOutputStream out = new ByteArrayOutputStream(size);
        try {
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            out.close();
            return out.toByteArray();
        } catch (IOException e) {
            Log.w("Favorite", "Could not write icon");
            return null;
        }
    }
 
}
